package com.hand.todo.app.service.impl;

import com.hand.todo.domain.entity.HodrSoHeader;
import com.hand.todo.app.service.SoHeaderService;
import com.hand.todo.domain.entity.HodrSoLine;
import com.hand.todo.domain.entity.SoHeaderVo;
import com.hand.todo.domain.repository.SoHeaderRepository;
import com.hand.todo.domain.repository.SoLineRepository;
import com.hand.todo.infra.mapper.SoHeaderMapper;
import com.hand.todo.infra.mapper.SoLineMapper;
import io.choerodon.core.domain.Page;
import io.choerodon.core.exception.CommonException;
import io.choerodon.mybatis.pagehelper.PageHelper;
import io.choerodon.mybatis.pagehelper.domain.PageRequest;
import org.apache.commons.collections.CollectionUtils;
import org.hzero.common.platform.CodeRuleVariable;
import org.hzero.core.base.BaseConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SoHeaderServiceImpl implements SoHeaderService {
    @Autowired
    private SoHeaderMapper headerMapper;
    @Autowired
    private SoLineMapper lineMapper;
    @Autowired
    private SoLineRepository lineRepository;

    @Override
    public Page<SoHeaderVo> queryHeaders(PageRequest pageRequest, HodrSoHeader soHeader) {
        Page<SoHeaderVo> headerVos = PageHelper.doPage(pageRequest, () -> headerMapper.queryHeaders(soHeader));
        return headerVos;
    }

    @Override
    public void deleteByList(List<Long> ids) {
        for (Long soHeaderId : ids) {
            HodrSoHeader exist = headerMapper.selectByPrimaryKey(soHeaderId);
            Assert.notNull(exist, BaseConstants.ErrorCode.DATA_NOT_EXISTS);
            // validate
            if (!"NEW".equals(exist.getOrderStatus()) && !"REJECTED".equals(exist.getOrderStatus())) {
                throw new CommonException("htdo.warn.soHeader.wrongStatus");
            }
            headerMapper.deleteByPrimaryKey(soHeaderId);
            List<HodrSoLine> soLines = lineMapper.selectBySoHeaderId(soHeaderId);
            if (CollectionUtils.isNotEmpty(soLines)) {
                lineRepository.batchDelete(soLines);
            }
        }
    }

    // TODO 实现在订单保存过程中对订单行的保存逻辑
    @Override
    public HodrSoHeader save(HodrSoHeader soHeader) {
        if (soHeader.getSoHeaderId() != null) {
            headerMapper.updateByPrimaryKey(soHeader);
        } else {
            soHeader.setOrderStatus("NEW");
            soHeader.setOrderNumber(HodrSoHeader.generateOrderNumber());
            headerMapper.insertSelective(soHeader);
        }
        List<HodrSoLine> soLines = soHeader.getSoLines();
        soLines.forEach(line -> {
            line.setSoHeaderId(soHeader.getSoHeaderId());
            if (line.getSoLineId() != null) {
                lineRepository.updateByPrimaryKey(line);
            } else {
                lineRepository.insertSelective(line);
            }
        });

        return soHeader;
    }

    @Override
    public HodrSoHeader update(HodrSoHeader soHeader) {
        Assert.notNull(soHeader.getSoHeaderId(), BaseConstants.ErrorCode.DATA_INVALID);
        HodrSoHeader entity = headerMapper.selectByPrimaryKey(soHeader.getSoHeaderId());
        Assert.notNull(entity, BaseConstants.ErrorCode.DATA_NOT_EXISTS);
        entity.setOrderNumber(soHeader.getOrderNumber());
        entity.setCompanyId(soHeader.getCompanyId());
        entity.setOrderDate(soHeader.getOrderDate());
        entity.setOrderStatus(soHeader.getOrderStatus());
        entity.setCustomerId(soHeader.getCustomerId());
        headerMapper.updateByPrimaryKey(entity);
        return entity;
    }

    @Override
    public void submit(Long tenantId, HodrSoHeader soHeader) {
        HodrSoHeader entity = validate(soHeader, tenantId);

//        String code = codeRuleBuilder.generateCode(CodeConstants.Level.TENANT, 0L, "DEMO", CodeConstants.CodeRuleLevelCode.CUSTOM, "GLOBAL", null);
        entity.setOrderNumber(HodrSoHeader.generateOrderNumber());

        entity.setCompanyId(soHeader.getCompanyId());
        entity.setOrderDate(soHeader.getOrderDate());
        entity.setOrderStatus("SUBMITTED");
        entity.setCustomerId(soHeader.getCustomerId());

        headerMapper.updateByPrimaryKey(entity);

        List<HodrSoLine> soLines = soHeader.getSoLines();
        List<HodrSoLine> soLineToUpdate = new ArrayList<>();
        List<HodrSoLine> soLineToCreate = new ArrayList<>();
        for (HodrSoLine soLine : soLines) {
            if (soLine.getSoLineId() == null) {
                // 新建
                soLineToCreate.add(soLine);
            } else {
                // 更新
                HodrSoLine exist = lineRepository.selectByPrimaryKey(soLine.getSoLineId());
                setSoLine(soLine, exist);
                soLineToUpdate.add(exist);
            }
        }
        lineRepository.batchInsertSelective(soLineToCreate);
        lineRepository.batchUpdateByPrimaryKey(soLineToUpdate);

    }

    @Override
    public void updateStatus(String oriStatus, String newStatus) {
        headerMapper.updateStatus(oriStatus, newStatus);
    }

    @Override
    public HodrSoHeader queryHeaderById(long id) {
        return headerMapper.selectByPrimaryKey(id);
    }

    private void setSoLine(HodrSoLine soLine, HodrSoLine newSoLine) {
        newSoLine.setSoHeaderId(soLine.getSoHeaderId());
        newSoLine.setLineNumber(soLine.getLineNumber());
        newSoLine.setItemId(soLine.getItemId());
        newSoLine.setOrderQuantity(soLine.getOrderQuantity());
        newSoLine.setUnitSellingPrice(soLine.getUnitSellingPrice());
        newSoLine.setDescription(soLine.getDescription());
        newSoLine.setAddition1(soLine.getAddition1());
        newSoLine.setAddition2(soLine.getAddition2());
        newSoLine.setAddition3(soLine.getAddition3());
        newSoLine.setAddition4(soLine.getAddition4());
        newSoLine.setAddition5(soLine.getAddition5());
    }

    private HodrSoHeader validate(HodrSoHeader soHeader, Long tenantId) {
        // 校验数据是否合法
        Assert.notNull(soHeader.getSoHeaderId(), BaseConstants.ErrorCode.DATA_INVALID);

        // 校验当前订单是否存在
        HodrSoHeader entity = headerMapper.selectByPrimaryKey(soHeader.getSoHeaderId());
        Assert.notNull(entity, BaseConstants.ErrorCode.DATA_NOT_EXISTS);

        // 校验当前用户是否与单据创建人一致
        if (!entity.getCreatedBy().equals(tenantId)) {
            throw new CommonException("当前用户无权提交该订单，请检查用户是否与单据创建人一致");
        }

        // 校验单据数据库状态
        if (!"NEW".equals(entity.getOrderStatus()) && !"REJECTED".equals(entity.getOrderStatus())) {
            throw new CommonException("htdo.warn.soHeader.wrongStatus");
        }
        return entity;
    }

}
